package bookworm;


import java.util.LinkedList;

import retrievedatafromrevishapi.AccessBooksData;


public class BestReviewersRecommendationsRetriever 
{
	
	/**
	 * these best reviewers are chosen by our criteria for evaluating reviewers.
	 * We give them a grade by looking in their reading history and number or reviews ratings
	 * and give each of these criteria a grade from 0 to 5(this grade is calculated based on an average
	 * which is described in class CalculatesRatingsBookworm). The best are the ones with rating equal to 5.
	 */
	private LinkedList<String> bestReviewersUserName;
	
	public BestReviewersRecommendationsRetriever()
	{
		this.bestReviewersUserName = new LinkedList<String>();
		//these best reviewers are based on our method of calculating a reviewer's rating 
		this.bestReviewersUserName.add("A. Bowdoin Van Riper");
		this.bestReviewersUserName.add("Elizabeth");
		this.bestReviewersUserName.add("jaemi");
		this.bestReviewersUserName.add("3rs");
		this.bestReviewersUserName.add("Tara");
		this.bestReviewersUserName.add("deargreenplace");
		this.bestReviewersUserName.add("Sundance");
		this.bestReviewersUserName.add("JustPeachy");
		this.bestReviewersUserName.add("max");
		
	}
	
	public LinkedList<String> getBestReviewersUserName()
	{
		return this.bestReviewersUserName;
	}
	
	
	public LinkedList<String> getTagsTopReviewerLikesToRead(String topReviewerName)
	{
		/*
		 * first, let's get the reviews which the reviewer wrote and are top rated by him/her. After
		 * all, these are the reviews the reviewer really liked. 
		 */
		LinkedList<Review> topReviewsFromReviewer = this.getAllTopRatedReviewsFromTopReviewer(topReviewerName);
		
		/*
		 * now, let's get the tags associated with the top reviews in most appearance order.
		 */
		
		LinkedList<String> tagsByMostAppearanceorder = FiltersReviewsByTag.getTagsOfReviewsByMostAppearanceOrder(topReviewsFromReviewer);
		
		//for now, let's get just the two tags the top reviewer likes to read most AND are tags used by our system
		LinkedList<String> tagsTopReviewerLikesToRead = new LinkedList<String>();
		LinkedList<String> allBookTagsUsedBySystem = AdministratorOfAllBookTagsUsedByTheSystem.getAllBookTags();
		
		int indexTagsByMostAppearanceOrder= 0;
		
		while(indexTagsByMostAppearanceOrder < tagsByMostAppearanceorder.size() && tagsTopReviewerLikesToRead.size() < 2)
		{
			String singleTagByMostAppearanceOrder = tagsByMostAppearanceorder.get(indexTagsByMostAppearanceOrder);
			if(allBookTagsUsedBySystem.contains(singleTagByMostAppearanceOrder) == true)
			{
				tagsTopReviewerLikesToRead.add(singleTagByMostAppearanceOrder);
			}
			
			indexTagsByMostAppearanceOrder = indexTagsByMostAppearanceOrder + 1;
		}
		
		return tagsTopReviewerLikesToRead;
	}
	
	
	public LinkedList<Book> getAllBookRecommendationsFromTopReviewer(String topReviewerName)
	{
		LinkedList<Review> topRatedReviews = getAllTopRatedReviewsFromTopReviewer(topReviewerName);
		/*now let's just convert these top review instances to book instances. After all,
		 * we're offering book recommendations and not book review recommendations. The reviews
		 * will be shown to the user later.
		 */
		LinkedList<Book> bookRecommendations =
				CreateBooksBasedOnReviews.createBooksFromReviews(topRatedReviews);
		
		return bookRecommendations;
		
	}

	public LinkedList<Review> getAllTopRatedReviewsFromTopReviewer(String topReviewerName) 
	{
		LinkedList<Review> allReviewsFromtheTopReviewer = getAllReviewsFromTopReviewer(topReviewerName);
		/*
		 * we don't want all the reviews from the top reviewer, right?
		 * what we want is his/her recommendations. this means the top rated reviews he/she wrote.
		 * Let's find these recommendations!
		 */
		
		LinkedList<Review> topRatedReviews = 
				this.getJustTheTopRatedReviews(allReviewsFromtheTopReviewer);
		return topRatedReviews;
	}
	
	
	

	private LinkedList<Review> getAllReviewsFromTopReviewer(String topReviewerName) 
	{
		//first, let's make a search for book reviews
		LinkedList<String> searchParameters = new LinkedList<String>();
		LinkedList<String> parametersValues = new LinkedList<String>();
		searchParameters.add("user");
		parametersValues.add(topReviewerName);
		
		/*
		 * let's get the instance responsible for providing unique access to all book data
		 * (can be book reading history or book reviews)
		 */
		AccessBooksData accessBooksData = AccessBooksData.getAccessBooksData();
		
		LinkedList<Review> allReviewsFromtheTopReviewer = 
				accessBooksData.getAllBookReviewsFromRevishAPI(searchParameters, parametersValues);
		return allReviewsFromtheTopReviewer;
	}
	
	
	/**
	 * apparently, Revish's API isn't working for minrating. This leaves us
	 * no choice but to make our system distinguish top rated reviews from the others.
	 * It's made in this method.
	 * @param allReviews all the reviews extracted from revish's API
	 * @return just the reviews with rating equal to 5.
	 */
	private LinkedList<Review> getJustTheTopRatedReviews(LinkedList<Review> allReviews)
	{
		LinkedList<Review> justTopRatedReviews = new LinkedList<Review>();
		for(int i = 0; i < allReviews.size(); i++)
		{
			Review singleReview = allReviews.get(i);
			int ratingOfSingleReview = singleReview.getRating();
			if(ratingOfSingleReview == 5)
			{
				justTopRatedReviews.add(singleReview);
			}
		}
		
		return justTopRatedReviews;
		
	}
	
	

}
